/**
 * 统一日志系统
 * 
 * 功能：
 * 1. 日志级别控制（DEBUG, INFO, WARN, ERROR）
 * 2. 日志分类（ECS, MVVM, Resource, Network, etc.）
 * 3. 格式化输出（时间戳、调用栈、颜色）
 * 4. 性能统计
 * 5. 日志过滤
 * 6. 开发/生产环境切换
 * 
 * @author AI Assistant
 * @date 2025-11-27
 */

// ============================================================================
// 日志级别枚举
// ============================================================================

/**
 * 日志级别
 */
export enum LogLevel {
    /** 调试信息 - 最详细 */
    DEBUG = 0,
    /** 常规信息 */
    INFO = 1,
    /** 警告信息 */
    WARN = 2,
    /** 错误信息 */
    ERROR = 3,
    /** 关闭所有日志 */
    NONE = 4,
}

// ============================================================================
// 日志分类枚举
// ============================================================================

/**
 * 日志分类
 */
export enum LogCategory {
    /** ECS 系统 */
    ECS = 'ECS',
    /** MVVM 架构 */
    MVVM = 'MVVM',
    /** 资源加载 */
    RESOURCE = 'Resource',
    /** 网络通信 */
    NETWORK = 'Network',
    /** 场景管理 */
    SCENE = 'Scene',
    /** 游戏逻辑 */
    GAME = 'Game',
    /** 性能监控 */
    PERFORMANCE = 'Performance',
    /** 用户界面 */
    UI = 'UI',
    /** 音频系统 */
    AUDIO = 'Audio',
    /** 物理系统 */
    PHYSICS = 'Physics',
    /** 动画系统 */
    ANIMATION = 'Animation',
    /** 通用 */
    GENERAL = 'General',
}

// ============================================================================
// 日志配置接口
// ============================================================================

/**
 * 日志配置
 */
export interface ILoggerConfig {
    /** 全局日志级别 */
    level: LogLevel;
    /** 是否显示时间戳 */
    showTimestamp: boolean;
    /** 是否显示调用栈 */
    showStackTrace: boolean;
    /** 是否启用颜色 */
    enableColor: boolean;
    /** 是否启用性能统计 */
    enablePerformanceStats: boolean;
    /** 分类过滤（仅显示这些分类的日志，为空则显示所有） */
    categoryFilter: LogCategory[];
    /** 分类级别覆盖（特定分类使用不同的日志级别） */
    categoryLevelOverrides: Map<LogCategory, LogLevel>;
}

// ============================================================================
// 日志输出接口
// ============================================================================

/**
 * 日志条目
 */
export interface ILogEntry {
    level: LogLevel;
    category: LogCategory;
    message: string;
    timestamp: number;
    data?: any;
    stackTrace?: string;
}

// ============================================================================
// 日志系统实现
// ============================================================================

/**
 * 统一日志系统
 */
export class Logger {
    private static instance: Logger;
    
    /** 配置 */
    private config: ILoggerConfig = {
        level: LogLevel.DEBUG,
        showTimestamp: true,
        showStackTrace: false,
        enableColor: true,
        enablePerformanceStats: false,
        categoryFilter: [],
        categoryLevelOverrides: new Map(),
    };
    
    /** 日志历史（用于调试） */
    private logHistory: ILogEntry[] = [];
    private readonly MAX_HISTORY_SIZE = 1000;
    
    /** 性能统计 */
    private stats = {
        totalLogs: 0,
        logsByLevel: new Map<LogLevel, number>(),
        logsByCategory: new Map<LogCategory, number>(),
    };
    
    /** 颜色映射 */
    private readonly colors = {
        [LogLevel.DEBUG]: '#888888',   // 灰色
        [LogLevel.INFO]: '#0099FF',    // 蓝色
        [LogLevel.WARN]: '#FF9900',    // 橙色
        [LogLevel.ERROR]: '#FF0000',   // 红色
    };
    
    /** 样式映射（支持字体大小、粗细等）*/
    private readonly styles = {
        [LogLevel.DEBUG]: 'color: #888888; font-size: 12px; font-weight: normal;',
        [LogLevel.INFO]: 'color: #0099FF; font-size: 13px; font-weight: normal;',
        [LogLevel.WARN]: 'color: #FF9900; font-size: 13px; font-weight: bold;',
        [LogLevel.ERROR]: 'color: #FF0000; font-size: 14px; font-weight: bold;',
    };
    
    /** 特殊样式（用于强调重要信息）*/
    readonly specialStyles = {
        title: 'color: #00CCFF; font-size: 16px; font-weight: bold; background: #1a1a1a; padding: 2px 8px;',
        success: 'color: #00FF00; font-size: 13px; font-weight: bold;',
        highlight: 'color: #FFFF00; font-size: 13px; font-weight: bold;',
        separator: 'color: #666666; font-size: 12px;',
        large: 'font-size: 16px; font-weight: bold;',
        medium: 'font-size: 14px; font-weight: normal;',
        small: 'font-size: 11px; font-weight: normal;',
    };
    
    /** 级别名称映射 */
    private readonly levelNames = {
        [LogLevel.DEBUG]: 'DEBUG',
        [LogLevel.INFO]: 'INFO',
        [LogLevel.WARN]: 'WARN',
        [LogLevel.ERROR]: 'ERROR',
    };
    
    private constructor() {
        this.initializeStats();
    }
    
    static getInstance(): Logger {
        if (!Logger.instance) {
            Logger.instance = new Logger();
        }
        return Logger.instance;
    }
    
    // ========================================================================
    // 配置方法
    // ========================================================================
    
    /**
     * 设置全局日志级别
     */
    setLevel(level: LogLevel): void {
        this.config.level = level;
    }
    
    /**
     * 设置分类日志级别
     */
    setCategoryLevel(category: LogCategory, level: LogLevel): void {
        this.config.categoryLevelOverrides.set(category, level);
    }
    
    /**
     * 设置分类过滤
     */
    setCategoryFilter(categories: LogCategory[]): void {
        this.config.categoryFilter = categories;
    }
    
    /**
     * 更新配置
     */
    configure(config: Partial<ILoggerConfig>): void {
        this.config = { ...this.config, ...config };
    }
    
    /**
     * 快速设置：开发模式
     */
    setDevelopmentMode(): void {
        this.config.level = LogLevel.DEBUG;
        this.config.showTimestamp = true;
        this.config.showStackTrace = false;
        this.config.enableColor = true;
        this.config.enablePerformanceStats = true;
    }
    
    /**
     * 快速设置：生产模式
     */
    setProductionMode(): void {
        this.config.level = LogLevel.WARN;
        this.config.showTimestamp = false;
        this.config.showStackTrace = false;
        this.config.enableColor = false;
        this.config.enablePerformanceStats = false;
    }
    
    // ========================================================================
    // 核心日志方法
    // ========================================================================
    
    /**
     * 调试日志
     */
    debug(category: LogCategory, message: string, data?: any): void {
        this.log(LogLevel.DEBUG, category, message, data);
    }
    
    /**
     * 信息日志
     */
    info(category: LogCategory, message: string, data?: any): void {
        this.log(LogLevel.INFO, category, message, data);
    }
    
    /**
     * 警告日志
     */
    warn(category: LogCategory, message: string, data?: any): void {
        this.log(LogLevel.WARN, category, message, data);
    }
    
    /**
     * 错误日志
     */
    error(category: LogCategory, message: string, data?: any): void {
        this.log(LogLevel.ERROR, category, message, data);
    }
    
    /**
     * 样式化日志（用于特殊强调）
     * 
     * @param message 消息内容
     * @param style 样式名称或自定义样式字符串
     * @param data 附加数据
     */
    styled(message: string, style: keyof typeof this.specialStyles | string, data?: any): void {
        if (!this.config.enableColor) {
            console.log(message);
            if (data !== undefined) {
                console.log('  数据:', data);
            }
            return;
        }
        
        const styleString = typeof style === 'string' && style in this.specialStyles
            ? this.specialStyles[style as keyof typeof this.specialStyles]
            : style;
            
        console.log(`%c${message}`, styleString);
        if (data !== undefined) {
            console.log('  数据:', data);
        }
    }
    
    /**
     * 核心日志方法
     */
    private log(level: LogLevel, category: LogCategory, message: string, data?: any): void {
        // 检查是否应该输出此日志
        if (!this.shouldLog(level, category)) {
            return;
        }
        
        // 创建日志条目
        const entry: ILogEntry = {
            level,
            category,
            message,
            timestamp: Date.now(),
            data,
        };
        
        // 添加调用栈
        if (this.config.showStackTrace && level >= LogLevel.WARN) {
            entry.stackTrace = new Error().stack;
        }
        
        // 保存到历史
        this.saveToHistory(entry);
        
        // 更新统计
        this.updateStats(level, category);
        
        // 输出日志
        this.output(entry);
    }
    
    // ========================================================================
    // 日志过滤
    // ========================================================================
    
    /**
     * 检查是否应该输出日志
     */
    private shouldLog(level: LogLevel, category: LogCategory): boolean {
        // 检查全局级别
        const effectiveLevel = this.config.categoryLevelOverrides.get(category) ?? this.config.level;
        if (level < effectiveLevel) {
            return false;
        }
        
        // 检查分类过滤
        if (this.config.categoryFilter.length > 0 && !this.config.categoryFilter.includes(category)) {
            return false;
        }
        
        return true;
    }
    
    // ========================================================================
    // 日志输出
    // ========================================================================
    
    /**
     * 输出日志
     */
    private output(entry: ILogEntry): void {
        const formattedMessage = this.formatMessage(entry);
        
        // 根据级别选择输出方法
        switch (entry.level) {
            case LogLevel.DEBUG:
                if (this.config.enableColor) {
                    console.log(`%c${formattedMessage}`, this.styles[entry.level]);
                } else {
                    console.log(formattedMessage);
                }
                break;
                
            case LogLevel.INFO:
                if (this.config.enableColor) {
                    console.info(`%c${formattedMessage}`, this.styles[entry.level]);
                } else {
                    console.info(formattedMessage);
                }
                break;
                
            case LogLevel.WARN:
                if (this.config.enableColor) {
                    console.warn(`%c${formattedMessage}`, this.styles[entry.level]);
                } else {
                    console.warn(formattedMessage);
                }
                break;
                
            case LogLevel.ERROR:
                if (this.config.enableColor) {
                    console.error(`%c${formattedMessage}`, this.styles[entry.level]);
                } else {
                    console.error(formattedMessage);
                }
                if (entry.stackTrace) {
                    console.error(entry.stackTrace);
                }
                break;
        }
        
        // 输出附加数据
        if (entry.data !== undefined) {
            console.log('  数据:', entry.data);
        }
    }
    
    /**
     * 格式化日志消息
     */
    private formatMessage(entry: ILogEntry): string {
        const parts: string[] = [];
        
        // 时间戳
        if (this.config.showTimestamp) {
            const date = new Date(entry.timestamp);
            const time = `${this.pad(date.getHours())}:${this.pad(date.getMinutes())}:${this.pad(date.getSeconds())}.${this.pad(date.getMilliseconds(), 3)}`;
            parts.push(`[${time}]`);
        }
        
        // 级别
        parts.push(`[${this.levelNames[entry.level as keyof typeof this.levelNames]}]`);
        
        // 分类
        parts.push(`[${entry.category}]`);
        
        // 消息
        parts.push(entry.message);
        
        return parts.join(' ');
    }
    
    /**
     * 数字补零
     */
    private pad(num: number, size: number = 2): string {
        let s = num.toString();
        while (s.length < size) s = '0' + s;
        return s;
    }
    
    // ========================================================================
    // 历史记录
    // ========================================================================
    
    /**
     * 保存到历史
     */
    private saveToHistory(entry: ILogEntry): void {
        this.logHistory.push(entry);
        
        // 限制历史大小
        if (this.logHistory.length > this.MAX_HISTORY_SIZE) {
            this.logHistory.shift();
        }
    }
    
    /**
     * 获取日志历史
     */
    getHistory(filter?: { level?: LogLevel; category?: LogCategory; limit?: number }): ILogEntry[] {
        let history = this.logHistory;
        
        // 过滤级别
        if (filter?.level !== undefined) {
            history = history.filter(e => e.level === filter.level);
        }
        
        // 过滤分类
        if (filter?.category !== undefined) {
            history = history.filter(e => e.category === filter.category);
        }
        
        // 限制数量
        if (filter?.limit !== undefined) {
            history = history.slice(-filter.limit);
        }
        
        return history;
    }
    
    /**
     * 清空历史
     */
    clearHistory(): void {
        this.logHistory = [];
    }
    
    // ========================================================================
    // 性能统计
    // ========================================================================
    
    /**
     * 初始化统计
     */
    private initializeStats(): void {
        for (const level of [LogLevel.DEBUG, LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR]) {
            this.stats.logsByLevel.set(level, 0);
        }
        
        for (const category in LogCategory) {
            this.stats.logsByCategory.set(LogCategory[category as keyof typeof LogCategory], 0);
        }
    }
    
    /**
     * 更新统计
     */
    private updateStats(level: LogLevel, category: LogCategory): void {
        if (!this.config.enablePerformanceStats) {
            return;
        }
        
        this.stats.totalLogs++;
        this.stats.logsByLevel.set(level, (this.stats.logsByLevel.get(level) || 0) + 1);
        this.stats.logsByCategory.set(category, (this.stats.logsByCategory.get(category) || 0) + 1);
    }
    
    /**
     * 获取统计信息
     */
    getStats() {
        return {
            totalLogs: this.stats.totalLogs,
            byLevel: Object.fromEntries(this.stats.logsByLevel),
            byCategory: Object.fromEntries(this.stats.logsByCategory),
        };
    }
    
    /**
     * 打印统计信息
     */
    printStats(): void {
        const separator = '━'.repeat(60);
        
        // 标题
        if (this.config.enableColor) {
            console.log(`%c${separator}`, this.specialStyles.separator);
            console.log(`%c📊 日志系统统计信息`, this.specialStyles.title);
            console.log(`%c${separator}`, this.specialStyles.separator);
        } else {
            console.log(separator);
            console.log('📊 日志系统统计信息');
            console.log(separator);
        }
        
        // 总日志数
        if (this.config.enableColor) {
            console.log(`%c总日志数: ${this.stats.totalLogs}`, 'color: #00CCFF; font-size: 14px; font-weight: bold;');
        } else {
            console.log(`总日志数: ${this.stats.totalLogs}`);
        }
        
        // 按级别统计
        console.log('');
        if (this.config.enableColor) {
            console.log(`%c📈 按级别统计`, this.specialStyles.large);
        } else {
            console.log('📈 按级别统计');
        }
        
        for (const [level, count] of this.stats.logsByLevel.entries()) {
            if (count > 0) {
                const levelName = this.levelNames[level as keyof typeof this.levelNames];
                const percentage = ((count / this.stats.totalLogs) * 100).toFixed(1);
                
                if (this.config.enableColor && level in this.styles) {
                    // 使用对应级别的颜色
                    const style = this.styles[level as keyof typeof this.styles];
                    console.log(`%c  ${levelName}: ${count} (${percentage}%)`, style);
                } else {
                    console.log(`  ${levelName}: ${count} (${percentage}%)`);
                }
            }
        }
        
        // 按分类统计
        console.log('');
        if (this.config.enableColor) {
            console.log(`%c🏷️  按分类统计`, this.specialStyles.large);
        } else {
            console.log('🏷️  按分类统计');
        }
        
        // 将分类统计转换为数组并排序（按数量降序）
        const categoryStats = Array.from(this.stats.logsByCategory.entries())
            .filter(([_, count]) => count > 0)
            .sort((a, b) => b[1] - a[1]);
        
        for (const [category, count] of categoryStats) {
            const percentage = ((count / this.stats.totalLogs) * 100).toFixed(1);
            const barLength = Math.round((count / this.stats.totalLogs) * 30); // 最大30个字符的进度条
            const bar = '█'.repeat(barLength) + '░'.repeat(30 - barLength);
            
            if (this.config.enableColor) {
                console.log(`%c  ${category}:`, 'color: #0099FF; font-weight: bold;');
                console.log(`%c    ${bar} ${count} (${percentage}%)`, 'color: #00FF88; font-size: 12px;');
            } else {
                console.log(`  ${category}: ${count} (${percentage}%)`);
                console.log(`    ${bar}`);
            }
        }
        
        // 底部分隔线
        console.log('');
        if (this.config.enableColor) {
            console.log(`%c${separator}`, this.specialStyles.separator);
        } else {
            console.log(separator);
        }
    }
    
    /**
     * 重置统计
     */
    resetStats(): void {
        this.stats.totalLogs = 0;
        this.initializeStats();
    }
}

// ============================================================================
// 全局单例和便捷方法
// ============================================================================

/**
 * 全局日志实例
 */
export const logger = Logger.getInstance();

/**
 * 便捷的日志方法（无需指定分类，使用 GENERAL）
 */
export const log = {
    debug: (message: string, data?: any) => logger.debug(LogCategory.GENERAL, message, data),
    info: (message: string, data?: any) => logger.info(LogCategory.GENERAL, message, data),
    warn: (message: string, data?: any) => logger.warn(LogCategory.GENERAL, message, data),
    error: (message: string, data?: any) => logger.error(LogCategory.GENERAL, message, data),
};

/**
 * 创建分类日志器
 */
export function createCategoryLogger(category: LogCategory) {
    return {
        debug: (message: string, data?: any) => logger.debug(category, message, data),
        info: (message: string, data?: any) => logger.info(category, message, data),
        warn: (message: string, data?: any) => logger.warn(category, message, data),
        error: (message: string, data?: any) => logger.error(category, message, data),
    };
}

